package br.ufmt.eit.cursos.util;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletResponse;

public class FileUtil 
{
	private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB.
	
	public static void geraCSV(StringBuffer sb, String nomeArquivo) throws IOException
	{
		// Prepare.
	    FacesContext facesContext = FacesContext.getCurrentInstance();
	    ExternalContext externalContext = facesContext.getExternalContext();
	    HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
	    DateFormat formatter = new SimpleDateFormat("yyyyMMdd");
	    Date data = new Date();
	    
	    BufferedOutputStream output = null;
	    
	    ByteArrayInputStream input = new ByteArrayInputStream(sb.toString().getBytes("UTF-8"));
	    try {
	        // Init servlet response.
	        response.reset();
	        response.setHeader("Content-Type", "application/csv");
	        response.setHeader("Content-Length", String.valueOf(input.available()));
	        response.setHeader("Content-Disposition", "attachment; filename=\"" + nomeArquivo + 
	        		"-" + formatter.format(data) + ".csv" + "\"");
	        output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);
	
	        // Write file contents to response.
	        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
	        int length;
	        while ((length = input.read(buffer)) > 0) {
	            output.write(buffer, 0, length);
	        }
	        
	        // Finalize task.
	        output.flush();
	    } 
	    finally 
	    {
	        // Gently close streams.
	        closeResource(output);
	        closeResource(input);
	    }
	
	    // Inform JSF that it doesn't need to handle response.
	    // This is very important, otherwise you will get the following exception in the logs:
	    // java.lang.IllegalStateException: Cannot forward after response has been committed.
	    facesContext.responseComplete();
	}
	
	// Helpers (can be refactored to public utility class) ----------------------------------------

	public static void downloadArquivo(InputStream input, String nomeArquivo, String extensao) throws IOException
	{
		// Prepare.
	    FacesContext facesContext = FacesContext.getCurrentInstance();
	    ExternalContext externalContext = facesContext.getExternalContext();
	    HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
	    DateFormat formatter = new SimpleDateFormat("yyyyMMdd");
	    Date data = new Date();
	    
	    BufferedOutputStream output = null;
	    
	    try {
	        // Init servlet response.
	        response.reset();
	        response.setHeader("Content-Type", "application/csv");
	        response.setHeader("Content-Length", String.valueOf(input.available()));
	        response.setHeader("Content-Disposition", "attachment; filename=\"" + nomeArquivo + 
	        		"-" + formatter.format(data) + "."+extensao+ "\"");
	        output = new BufferedOutputStream(response.getOutputStream(), 20480);
	
	        // Write file contents to response.
	        byte[] buffer = new byte[20480];
	        int length;
	        while ((length = input.read(buffer)) > 0) {
	            output.write(buffer, 0, length);
	        }
	        
	        // Finalize task.
	        output.flush();
	    } 
	    finally 
	    {
	        // Gently close streams.
	        closeResource(output);
	        closeResource(input);
	    }
	
	    // Inform JSF that it doesn't need to handle response.
	    // This is very important, otherwise you will get the following exception in the logs:
	    // java.lang.IllegalStateException: Cannot forward after response has been committed.
	    facesContext.responseComplete();
	}
    private static void closeResource(Closeable resource) {
        if (resource != null) {
            try {
                resource.close();
            } catch (IOException e) {
                // Do your thing with the exception. Print it, log it or mail it. It may be useful to 
                // know that this will generally only be thrown when the client aborted the download.
                e.printStackTrace();
            }
        }
    }
}
